#pragma once
#include <functional>
#include <string>
#include <unordered_map>
namespace cpp_component
{

template <typename T> class event
{
   public:
    event() = default;
    ~event() = default;

    template <typename... Args> void notify(const std::string &key, Args &&... args)
    {
        for (auto subscriber : m_subscribers)
        {
            if (key == subscriber.first)
                subscriber.second(std::forward<Args>(args)...);
        }
    }
    template <typename... Args> void notify_all(Args &&... args)
    {
        for (auto subscriber : m_subscribers)
        {
            subscriber.second(std::forward<Args>(args)...);
        }
    }
    bool subscribe(const std::string &key, const T function)
    {
        m_subscribers.emplace(key, function);
        return true;
    }

    bool unsubscribe(const std::string &key, const T function)
    {
        auto ps = m_subscribers.equal_range(key);
        for (auto it = ps.first; it != ps.second; it++)
        {
            if (it->second == function)
            {
                m_subscribers.erase(it++);
                return false;
            }
        }
        return false;
    }

   private:
    std::unordered_multimap<std::string, T* > m_subscribers;
};  // namespace cpp_component
}  // namespace cpp_component
